package com.lin.pay.paypal.v1;

import com.google.gson.Gson;
import com.lin.common.constant.CustomerRedisConstant;
import com.lin.common.utils.HttpClientUtils;
import com.lin.pay.paypal.v1.vo.CreatePaymentDto;
import com.lin.pay.paypal.v1.vo.CreatePaymentReqVo;
import com.lin.pay.paypal.v1.vo.ExecutePaymentsVo;
import com.lin.pay.paypal.v1.vo.TokenResult;
import com.lin.pay.wx.service.WxServiceImpl;
import com.lin.properties.PayProperties;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.message.BasicHeader;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class PaymentService {
    private static final Logger log = LoggerFactory.getLogger(WxServiceImpl.class);
    @Autowired
    private PayProperties payProperties;
    @Autowired
    private RedissonClient redissonClient;

    public String executePayments(String paymentID, String payerID) throws UnsupportedEncodingException {
        ExecutePaymentsVo vo = new ExecutePaymentsVo();
        vo.setPayer_id(payerID);
        String url = payProperties.getPaypal().get(PayProperties.EXECUTE_PAYMENT_URL);

        String result = HttpClientUtils.httpPost(url.replace("{payment_id}", paymentID), vo, buildHeader(getToken()));
        return result;
    }

    public String createPayment(CreatePaymentReqVo reqMsg) throws UnsupportedEncodingException {
        CreatePaymentDto req = Helper.getCreatePaymentData(reqMsg, payProperties.getPaypal().get(PayProperties.RETURN_URL), payProperties.getPaypal().get(PayProperties.CANCEL_URL));
        String result = HttpClientUtils.httpPost(payProperties.getPaypal().get(PayProperties.CREATE_PAYMENT_URL), req, buildHeader(getToken()));
        return result;
    }

    public String getToken() throws UnsupportedEncodingException {
        RBucket<String> rb = redissonClient.getBucket(CustomerRedisConstant.PAYPAL_ACCESS_TOKEN);
        if (rb.get() == null) {
            Header[] headers = new Header[]{
                    new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded"),
                    new BasicHeader(HttpHeaders.AUTHORIZATION, PaypalUtils.getBasicBearerToken(payProperties.getPaypal().get(PayProperties.CLIENT_ID), payProperties.getPaypal().get(PayProperties.CLIENT_SECRET))),
                    new BasicHeader("PayPal-Partner-Attribution-Id", PayProperties.BN_CODE)
            };
            Map<String, String> map = new HashMap<>();
            map.put("grant_type", "client_credentials");
            String s = HttpClientUtils.post(payProperties.getPaypal().get(PayProperties.ACCESS_TOKEN_URL), map, headers);
            log.info("access_token is: {}", s);
            Gson g = new Gson();
            TokenResult tr = g.fromJson(s, TokenResult.class);
            rb.set(tr.getAccess_token(), CustomerRedisConstant.PAYPAL_ACCESS_TOKEN_TIMEOUT, TimeUnit.SECONDS);
            return tr.getAccess_token();
        } else {
            log.info("access_token get by redis");
            return rb.get();
        }
    }

    private Header[] buildHeader(String accessToken) {
        return new Header[]{
                new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/json"),
                new BasicHeader(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken),
                new BasicHeader("PayPal-Partner-Attribution-Id", PayProperties.BN_CODE)
        };
    }

    public void setPayProperties(PayProperties payProperties) {
        this.payProperties = payProperties;
    }

    public void setRedissonClient(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }
}
